﻿using System.Collections.Generic;
using System.Numerics;
using System.Threading.Tasks;

namespace NavPlus
{
    /// <summary>
    /// 地图类数据结构
    /// </summary>
    public class NavMapLogic
    {
        int m_Width;
        int m_Height;

        NavGridLogic[,] m_NavGrids;

        /// <summary>
        ///  初始化地图数据
        /// </summary>
        /// <param name="width"></param>
        /// <param name="height"></param>
        public void InitNavMapLogic(int  width, int height)
        {
            m_Width = width;
            m_Height = height;

            m_NavGrids = new NavGridLogic[m_Width, m_Height];
            for (int i = 0; i < m_Width; i++)
            {
                for (int j = 0; j < m_Height; j++)
                {
                    NavGridLogic grid = new();
                    grid.InitNavGridLogic(i, j);
                    m_NavGrids[i, j] = grid;
                }
            }
        }

        /// <summary>
        /// 反初始化地图数据
        /// </summary>
        public void UnInitNavMapLogic()
        {
            for (int i = 0; i < m_Width; i++)
            {
                for (int j = 0; j < m_Height; j++)
                {
                    m_NavGrids[i, j].UnInitNavGridLogic();
                    // m_NavGrids[i, j] = null;
                }
            }
        }

        public Task<List<NavGridLogic>> CalcPath(NavGridLogic startPoint, NavGridLogic endPoint, BaseNavigation strategy)
        {
            return strategy.CalcPath(startPoint, endPoint);
        }

        #region 保存可行走区域的状态
        bool[,] stateArr = null;
        public void SaveWalkableState()
        {
            stateArr = new bool[m_Width, m_Height];
            for (int i = 0; i < m_Width; i++)
            {
                for (int j = 0; j < m_Height; j++)
                {
                    stateArr[i, j] = m_NavGrids[i, j].IsWalkable ;
                }
            }
        }
        public void LoadWalkableState()
        {
            if (stateArr != null)
            {
                for (int i = 0; i < m_Width; i++)
                {
                    for (int j = 0; j < m_Height; j++)
                    {
                        m_NavGrids[i, j].SetWalkableState(stateArr[i, j]);
                    }
                }
                stateArr = null;
            }
        }

        #endregion


        /// <summary>
        /// 更新地图中各地块的邻居信息
        /// </summary>
        public void UpdateNavMapData()
        {
            for (int i = 0; i < m_Width; i++)
            {
                for (int j = 0; j < m_Height; j++)
                {
                    if (m_NavGrids[i, j].IsWalkable)
                    {
                        m_NavGrids[i, j].m_NeighborGrids = GetNeighborGridLst(i, j);
                    }
                }
            }
        }
        // 偏移数组
        readonly Vector2[] OffsetArray = 
        {
            // 顺时针查找
            // new Vector2(-1, 1),
            // new Vector2(0, 1),
            // new Vector2(1, 1),
            // new Vector2(1, 0),
            // new Vector2(1, -1),
            // new Vector2(0, -1),
            // new Vector2(-1, -1),
            // new Vector2(-1, 0),

            // 优先 上 / 下 / 左 / 右
            new Vector2(0, 1),
            new Vector2(0, -1),
            new Vector2(-1, 0),
            new Vector2(1, 0),
            new Vector2(-1, 1),
            new Vector2(1, 1),
            new Vector2(1, -1),
            new Vector2(-1, -1),
        };

        // 获取邻居数组的方法逻辑
        List<NavGridLogic> GetNeighborGridLst(int x, int y)
        {
            List <NavGridLogic> ret = new List <NavGridLogic>();
            for (int i = 0; i < OffsetArray.Length; i++)
            {
                int offsetX = x + (int)OffsetArray[i].X;
                int offsetY = y + (int)OffsetArray[i].Y;
                if (InsideBorder(offsetX, offsetY) && m_NavGrids[offsetX, offsetY].IsWalkable)
                {
                    ret.Add(m_NavGrids[offsetX, offsetY]);
                }
            }
            return ret;
        }

        // 判断目标位置是否越界
        bool InsideBorder(int x, int y)
        {
            if (x >= 0 && x < m_Width
             && y >= 0 && y < m_Height)
                return true;
            return false;
        }
    }
}
